﻿using System.Linq;
using Cms.Application.Admin.Views;
using Cms.Application.IO;
using Cms.Data;
using Cms.Domain;
using Cms.Domain.RepositoryInterfaces;

namespace Cms.Application.Admin.Presenters
{
    public class ConfigureFirstSitePresenter : BasePresenter
    {
        private readonly Administrator _administrator;
        private readonly IConfigureFirstSiteView _view;

        public IDiskAccess DiskAccess { get; set; }
        
        public ConfigureFirstSitePresenter(IConfigureFirstSiteView view)
            : this(view, new RepositoryFactory())
        {
            DiskAccess = new DiskAccess();
        }
        
        public ConfigureFirstSitePresenter(IConfigureFirstSiteView view, IRepositoryFactory repositoryFactory)
            : base(view, repositoryFactory)
        {
            _view = view;
            _administrator = AdministratorRepository.GetAdministrator(_view.AdministratorID);
            if (!_administrator.HasPermission.ConfigureFirstSite || SiteRepository.GetSites().Count > 0)
                _view.ConfigureFirstSiteNotAllowed();
        }
        
        public void Initialize()
        {
            _view.RootMediaFolder = "media";
        }
        
        public void Validate()
        {
            if (_view.Domain == string.Empty)
                AddValidationError(GetText(_view, "NoDomainError"));
            else
            {
                if (DomainExists())
                    AddValidationError(GetText(_view, "DomainAlreadyInUseError"));
            }
            if (_view.DefaultLocaleName == string.Empty)
                AddValidationError(GetText(_view, "NoDefaultLocaleNameError"));
            if (_view.DefaultLocaleRegion == string.Empty)
                AddValidationError(GetText(_view, "NoDefaultLocaleRegionError"));
            if (_view.DefaultLocaleLanguage == string.Empty)
                AddValidationError(GetText(_view, "NoDefaultLocaleLanguageError"));
            if (_view.DefaultLocaleCode == string.Empty)
                AddValidationError(GetText(_view, "NoDefaultLocaleCodeError"));
            if (_view.RootMediaFolder == string.Empty)
                AddValidationError(GetText(_view, "NoRootMediaFolderError"));
            else
            {
                switch (_view.RootMediaFolder.ToLower())
                {
                    case "__system":
                    case "admin":
                    case "swfupload":
                        AddValidationError(GetText(_view, "RootMediaFolderNameNotAllowedError"));
                        break;
                }
            }
        }
        
        public void Save()
        {
            Validate();
            if (!IsValid)
                return;
            var site = new Site();
            var locale = new Locale();
            var localeTranslation = new LocaleTranslation();
            site.Domain = _view.Domain;
            site.RootMediaFolder = _view.RootMediaFolder;
            site.Online = true;
            site.Locales.Add(locale);
            site.DefaultLocale = locale;
            locale.UrlCode = _view.DefaultLocaleCode;
            locale.Site = site;
            SiteRepository.SaveSite(site); // Save to get an ID for the locale
            localeTranslation.Name = _view.DefaultLocaleName;
            localeTranslation.Language = _view.DefaultLocaleLanguage;
            localeTranslation.Region = _view.DefaultLocaleRegion;
            locale.Translations.Add(locale.ID, localeTranslation);
            SiteRepository.SaveSite(site); // Save again to persist the locale translation
            _administrator.CurrentSite = site;
            _administrator.DefaultSite = site;
            _administrator.AvailableSites.Add(site);
            site.Administrators.Add(_administrator);
            _administrator.CurrentSiteLocale = locale;
            AdministratorRepository.SaveAdministrator(_administrator);
            DiskAccess.CreateDirectory(_view.RootMediaFolder);
        }

        private bool DomainExists()
        {
            bool domainExists = false;
            foreach (Site existingSite in SiteRepository.GetSites())
            {
                if (_view.Domain.ToLower() == existingSite.Domain.ToLower())
                {
                    domainExists = true;
                    break;
                }
                if (existingSite.AliasDomains.Any(alias => _view.Domain.ToLower() == alias.ToLower()))
                {
                    domainExists = true;
                }
                if (
                    existingSite.Locales.Any(
                        existingLocale => _view.Domain.ToLower() == existingLocale.AliasDomain.ToLower()))
                {
                    domainExists = true;
                }
                if (domainExists)
                    break;
            }
            return domainExists;
        }
    }
}